/**
 * 循环字节队列
 * Copyright (c) 2017 深圳市智辰科技有限公司
 * All rights reserved.
 * 张勇 41204@qq.com
 */

#ifndef _QCHAR_H_
#define _QCHAR_H_

#include <stdint.h>
#include <stdbool.h>
#include "utils.h"
#include "unios.h"

#ifdef __cplusplus
extern "C" {
#endif


// 打开动态内存分配支持
#define configSUPPORT_DYNAMIC_ALLOCATION 1

// 队列数据结构
typedef struct stQChar {
	uint16_t size;		///< 队列大小
	uint8_t *array;		///< 数据存储区
	uint16_t head;		///< 头部位置
	uint16_t tail;		///< 尾部位置
	bool full;		    ///< 队列满
	unios_ms_t timestamp;	///< 最后一个数据的时间戳(ms)
	unios_critical_section_t css; ///< 临界区
} QChar;

/// @brief 静态定义一个队列
/// @param name: 队列指针变量名称
#define QCharDef(name, size) \
	static uint8_t __##name##_Buffer__[size]; \
	static QChar __##name##_QChar__ = { size, __##name##_Buffer__, 0, 0, false, 0, osCriticalInitValue }; \
	QChar *name = &(__##name##_QChar__)

#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
	/// @brief 动态创建一个队列
	QChar* QChar_create(uint16_t size);
	/// @brief 释放动态创建的队列
	void QChar_destroy(QChar *q);
#endif


/// @brief 队列计数
uint16_t QChar_count(QChar *q);
/// @brief 队列中剩余空间大小
#define QChar_free(q)	(q->size - QChar_count(q))
/// @brief 队列是否满了
#define QChar_full(q)	(q->full)
/// @brief 锁定队列
#define QChar_lock(q)   unios_critical_section_enter((q)->css, 1000)
/// @brief 解锁队列
#define QChar_unlock(q) unios_critical_section_leave((q)->css)

/// @brief 清空队列
uint16_t QChar_clear(QChar *q);

/// @brief 向队列的最后面添加一个或多个元素(入队)
bool QChar_put(QChar *q, uint8_t item);
bool QChar_putn(QChar *q, uint8_t *buf, uint16_t size);

/// @brief 从队列的最前面取出一个元素(出队)
bool QChar_pop(QChar *q, uint8_t *item);
/// @brief 从队列的最前面取出多个元素(出队)，如果不够，则以实际返回的数量为准
uint16_t QChar_popn(QChar *q, uint8_t *buf, uint16_t size);

/// @brief 从队列中取得一个元素（并不出队）
bool QChar_peekAt(QChar *q, int idx, uint8_t *item);
/// @brief 从队列的最前面取得多个元素(并不出队)，如果不够，则以实际返回的数量为准
uint16_t QChar_peekn(QChar *q, uint8_t *buf, uint16_t size);

/// @brief 从队列的最后面删除一个或多个元素
bool QChar_cutn(QChar *q, uint16_t size);
#define QChar_cut(q)	QChar_cutn(q, 1)

/// @brief 队列中数据的寿命(ms)
unios_ms_t QChar_age(QChar *q);


#ifdef __cplusplus
}
#endif

#endif // _QCHAR_H_
